#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
    aliyun_oss.py
    ~~~~~~~~~~~~~~~~~~~~~~~
    :copyright: (c) 2020, Tungee
    :date created: 2020-01-10, 10:15:44
    :python version: 2.7
"""

import os
import traceback

import oss2


def get_oss_bucket(bucket_name, access_id, access_secret, end_point):
    auth = oss2.Auth(access_key_id=access_id, access_key_secret=access_secret)
    return oss2.Bucket(auth=auth, endpoint=end_point, bucket_name=bucket_name)


config = {
    'OSS': {
        'host': 'oss-cn-shenzhen-internal.aliyuncs.com',
        'bucket': 'tangee-spider',
        'access_key_id': 'LTAI4FpPCUk6jDynPrwQznHQ',
        'access_key_secret': 'z4s3Qn34dVUEcDo6yuROGME8poKfiI',
        'result_root': 'log',
    }
}


class OssHandler(object):
    """
    oss文件处理器
    """

    def __init__(self):
        self.output_bucket = get_oss_bucket(
            config['OSS']['bucket'],
            config['OSS']['access_key_id'],
            config['OSS']['access_key_secret'],
            config['OSS']['host'],
        )

    def upload_file(self, fp, oss_fp, remove_source=False):
        """ 上传文件到oss
        """
        try:
            self._upload_file(fp, oss_fp)
        except:
            print(traceback.format_exc())
            return False
        if remove_source:
            os.remove(fp)
        return True

    def _upload_file(self, local_path, oss_key):
        """ 切片上传文件
        """
        total_size = os.path.getsize(local_path)
        part_size = oss2.determine_part_size(
            total_size, preferred_size=1 * 1024 * 1024 * 1024)
        # 初始化分片上传，得到Upload ID。接下来的接口都要用到这个Upload ID。
        upload_id = self.output_bucket.init_multipart_upload(oss_key).upload_id
        # 逐个上传分片
        # 其中oss2.SizedFileAdapter()把file_obj转换为一个新的文件对象，
        # 新的文件对象可读的长度等于num_to_upload
        with open(local_path, 'rb') as file_obj:
            parts = []
            part_number = 1
            offset = 0
            while offset < total_size:
                num_to_upload = min(part_size, total_size - offset)
                result = self.output_bucket.upload_part(
                    oss_key, upload_id, part_number,
                    oss2.SizedFileAdapter(file_obj, num_to_upload))
                parts.append(oss2.models.PartInfo(part_number, result.etag))
                offset += num_to_upload
                part_number += 1
        # 完成分片上传
        if parts:
            self.output_bucket.complete_multipart_upload(oss_key, upload_id, parts)


def upload_to_oss(local_path, oss_filename):
    oss_key = os.path.join(config['OSS']['result_root'], os.path.basename(oss_filename))
    handler = OssHandler()
    a = handler.upload_file(local_path, oss_key, remove_source=False)
    print('uploads: {}'.format(a))
    return a


if __name__ == "__main__":
    local_path = '/mnt5/benniao.zip'
    file_name = '20200515_benniao.zip'
    upload_to_oss(local_path, file_name)
